home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
051-075
/
disk_054
/
ispell
/
ispell.el
< prev
next >
Wrap
Lisp/Scheme
|
1992-05-06
|
10KB
|
274 lines
;;; Spelling correction interface for GNU EMACS using "ispell"
;;; Walt Buehring
;;; Texas Instruments - Computer Science Center
;;; ARPA: Buehring%TI-CSL@CSNet-Relay
;;; UUCP: {smu, texsun, im4u, rice} ! ti-csl ! buehring
;;; ispell-region and associate routines added by
;;; Perry Smith
;;; pedz@bobkat
;;; Tue Jan 13 20:18:02 CST 1987
;;; Depends on the ispell program snarfed from MIT-PREP in early
;;; 1986. The only interactive command is "ispell-word" which should be
;;; bound to M-$. If someone writes an "ispell-region" command,
;;; I would appreciate a copy.
;;; To fully install this, add this file to your GNU lisp directory and
;;; compile it with M-X byte-compile-file. Then add the following to the
;;; appropriate init file:
;;; (autoload 'ispell-word "ispell"
;;; "Check the spelling of word in buffer." t)
;;; (global-set-key "\e$" 'ispell-word)
;;; If run on a heavily loaded system, the timeout value in ispell-check
;;; and the initial sleep time in ispell-init-process may need to be increased.
;;; No warranty expressed or implied. All sales final. Void where prohibited.
;;; If you don't like it, change it.
(defvar ispell-syntax-table nil)
(if (null ispell-syntax-table)
;; The following assumes that the standard-syntax-table
;; is static. If you add words with funky characters
;; to your dictionary, the following may have to change.
(progn
(setq ispell-syntax-table (make-syntax-table))
;; Make certain characters word constituents
;; (modify-syntax-entry ?' "w " ispell-syntax-table)
;; (modify-syntax-entry ?- "w " ispell-syntax-table)
;; Get rid on existing word syntax on certain characters
(modify-syntax-entry ?0 ". " ispell-syntax-table)
(modify-syntax-entry ?1 ". " ispell-syntax-table)
(modify-syntax-entry ?2 ". " ispell-syntax-table)
(modify-syntax-entry ?3 ". " ispell-syntax-table)
(modify-syntax-entry ?4 ". " ispell-syntax-table)
(modify-syntax-entry ?5 ". " ispell-syntax-table)
(modify-syntax-entry ?6 ". " ispell-syntax-table)
(modify-syntax-entry ?7 ". " ispell-syntax-table)
(modify-syntax-entry ?8 ". " ispell-syntax-table)
(modify-syntax-entry ?9 ". " ispell-syntax-table)
(modify-syntax-entry ?$ ". " ispell-syntax-table)
(modify-syntax-entry ?% ". " ispell-syntax-table)))
(defun ispell-word (&optional quietly)
"Check spelling of word at or before dot.
If word not found in dictionary, display possible corrections in a window
and let user select."
(interactive)
(let* ((current-syntax (syntax-table))
start end word poss replace)
(unwind-protect
(save-excursion
;; Ensure syntax table is reasonable
(set-syntax-table ispell-syntax-table)
;; Move backward for word if not already on one.
(if (not (looking-at "\\w"))
(re-search-backward "\\w" (dot-min) 'stay))
;; Move to start of word
(re-search-backward "\\W" (dot-min) 'stay)
;; Find start and end of word
(or (re-search-forward "\\w+" nil t)
(error "No word to check."))
(setq start (match-beginning 0)
end (match-end 0)
word (buffer-substring start end)))
(set-syntax-table current-syntax))
(or quietly (message "Checking spelling of %s..." (upcase word)))
(setq poss (ispell-check word))
(cond ((eq poss t)
(or quietly (message "Found %s" (upcase word))))
((stringp poss)
(or quietly (message "Found it because of %s" (upcase poss))))
((null poss)
(or quietly (message "Could Not Find %s" (upcase word))))
(t (setq replace (ispell-choose poss word))
(if replace
(progn
(goto-char end)
(delete-region start end)
(insert-string replace)))))
poss))
(defun ispell-choose (choices word)
"Display possible corrections from list CHOICES. Return chosen word
if one is chosen; Return nil to keep word"
(unwind-protect
(save-window-excursion
(let ((count 0)
(words choices)
(window-min-height 2)
char num result)
(overlay-window 3)
(switch-to-buffer "*Choices*") (erase-buffer)
(setq mode-line-format "-- %b --")
(while words
(if (> (+ 7 (current-column) (length (car words))) (window-width))
(insert "\n"))
(insert "(" (+ count ?1) ") " (car words) " ")
(setq words (cdr words)
count (1+ count)))
(select-window (next-window))
(while (eq t
(setq result
(progn
(message "Enter letter to replace word; Space to flush")
(setq char (upcase (read-char)))
(setq num (- char ?1))
(cond ((= char ? ) nil)
((= char ?I)
(ispell-check (concat "*" word))
nil)
((= char ?A)
(ispell-check (concat "@" word))
nil)
((= char ?R) (read-string "Replacement: " nil))
((and (>= num 0) (< num count)) (nth num choices))
(t (ding) t))))))
result))
;; Protected forms...
(bury-buffer "*Choices*")))
(defun overlay-window (height)
"Create a (usually small) window with HEIGHT lines and avoid
recentering."
(save-excursion
(let ((oldot (save-excursion (beginning-of-line) (dot)))
(top (save-excursion (move-to-window-line height) (dot)))
newin)
(if (< oldot top) (setq top oldot))
(setq newin (split-window-vertically height))
(set-window-start newin top))))
(defvar ispell-process nil
"Holds the process object for 'ispell'")
;;; create signal used by ispell-filter and ispell-check
(put 'ispell-output 'error-conditions '(ispell-output))
(defun ispell-check (word)
"Check spelling of string WORD, return either t for an exact match, a string
containing the root word for a match via suffix removal, a list of possible
correct spellings, or nil for a complete miss."
(ispell-init-process)
(send-string ispell-process (concat word "\n"))
(condition-case output
(progn
(sleep-for 20)
(error "Timeout waiting for ispell process output"))
(ispell-output (ispell-parse-output (car (cdr output))))))
(defun ispell-parse-output (output)
"Parse the OUTPUT string of 'ispell' and return a value as specified by the
'ispell-check' function."
(cond
((string= output "*") t)
((string= output "#") nil)
((string= (substring output 0 1) "+")
(substring output 2))
(t
(let ((choice-list '()))
(while (not (string= output ""))
(let* ((start (string-match "[A-z]" output))
(end (string-match " \\|$" output start)))
(if start
(setq choice-list (cons (substring output start end)
choice-list)))
(setq output (substring output (1+ end)))))
choice-list))))
(defvar ispell-process-output ""
"Holds partial output from the 'ispell' process")
(defun ispell-filter (process output)
"The filter-function for 'ispell'. Signals complete line using the
ispell-output signal"
(if (string= "\n" (substring output (1- (length output))))
(progn
(setq output (concat ispell-process-output
(substring output 0 (1- (length output))))
ispell-process-output "")
(signal 'ispell-output (list output)))
(setq ispell-process-output (concat ispell-process-output output))))
(defun ispell-init-process ()
"Check status of 'ispell' process and start if necessary; set up
filter function for output."
(if (or (not ispell-process)
(not (eq (process-status ispell-process) 'run)))
(progn
(message "Starting new ispell process...")
(and (get-buffer "*ispell*") (kill-buffer "*ispell*"))
(setq ispell-process (start-process "ispell" "*ispell*"
"ispell" "-a"))
(set-process-filter ispell-process 'ispell-filter)
(process-kill-without-query ispell-process)
(sit-for 3))))
(defvar ispell-filter-hook "/bin/cat"
"Filter to pass a region through before sending it to ispell.
Typically this is set to cat, deroff, detex, etc.")
(make-variable-buffer-local 'ispell-filter-hook)
(defvar ispell-filter-hook-args nil
"Arguments to pass to ispell-filter-hook")
(make-variable-buffer-local 'ispell-filter-hook-args)
; This routine has certain limitations brought about by the filter
; hook. For example, deroff will take ``\fBcat\fR'' and spit out
; ``cat''. This is hard to search for since word-search-forward will
; not match at all and search-forward for ``cat'' will match
; ``concatinate'' if it happens to occur before. I attempt to
; minimize these problems by always searching for each word in the
; original buffer even if it is not misspelled. This slows things
; down.
(defun ispell-region (start end)
"Check a region for spelling errors interactively. The variable
which should be buffer or mode specific ispell-filter-hook is called
to filter out text processing commands."
(interactive "r")
(let ((this-buf (current-buffer))
(spell-buf (get-buffer-create "ispell-temp"))
(current-syntax (syntax-table))
word poss replace word-start word-end)
(unwind-protect
(save-excursion
(set-buffer spell-buf)
(erase-buffer)
(set-buffer this-buf)
(if ispell-filter-hook-args
(call-process-region start end ispell-filter-hook nil
spell-buf nil ispell-filter-hook-args)
(call-process-region start end ispell-filter-hook nil
spell-buf nil))
(goto-char start)
(set-buffer spell-buf)
(set-syntax-table ispell-syntax-table)
(goto-char (point-min))
(while (progn
(message "Looking for a misspelled word")
(re-search-forward "\\W*\\(\\w+\\)" nil t))
(setq word (buffer-substring (setq word-start (match-beginning 1))
(setq word-end (match-end 1))))
(setq poss (ispell-check word))
(set-buffer this-buf)
(or (search-forward word nil t)
(error "Can not find %s in original text" word))
(if (not (or (eq poss t) (stringp poss))) ;bad word
(progn
(sit-for 0)
(setq replace (ispell-choose poss word))
(if replace
(replace-match replace))))
(set-buffer spell-buf)))
(set-syntax-table current-syntax))))